package com.chianghao.rockframewrok.core.db.manage.impl;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.chianghao.rockframewrok.core.db.manage.AbstractDataMeta;
import com.chianghao.rockframewrok.core.db.model.Column;
import com.chianghao.rockframewrok.core.db.model.ColumnType;
import com.chianghao.rockframewrok.core.db.model.Table;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MysqlDataMeta extends AbstractDataMeta {

	
	Logger log = LoggerFactory.getLogger(this.getClass());
	
	/**
	 * 获取删除字段的脚本
	 */
	@Override
	public String getDelColumnCommands(String tableName, String columnName) {
		return "DROP COLUMN `"+columnName+"`";
//		List<String> commands = new ArrayList<String>();
//		commands.add(" ALTER TABLE " + tableName + " DROP " + columnName + ";");
//		return commands;
	}

	@Override
	public String createTableDDL(Table table) {
		StringBuffer sb = new StringBuffer(" create table `" + table.getTableName() + "` ( ");
		for (String key : table.getColumnMap().keySet()) {
			log.info("===========the column info is {}===={}======",key,table.getColumnMap().get(key));
			Column column = table.getColumnMap().get(key);
			String columnSql = getColumnSql(column);
			sb.append(columnSql + ",");
		}
		Set<String> colomnskeys = table.getPrimaryKeys();
		if (colomnskeys != null && colomnskeys.size() > 0) {
			String primarykeysql = "PRIMARY KEY(";
			for (String key : colomnskeys) {
				primarykeysql += "`"+key + "`,";
			}
			if (primarykeysql.endsWith(",")) {
				primarykeysql = primarykeysql.substring(0, primarykeysql.lastIndexOf(","));
			}
			primarykeysql += ")";
			sb.append(primarykeysql);
		}

		String sql = sb.toString();
		if (sql.endsWith(",")) {
			sql = sql.substring(0, sql.lastIndexOf(","));
		}
		sql = sql + ");";
		return  sql;
	}

	@Override
	public List<String> alterTableDDL(Table table) {
		List<String> commonds = new ArrayList<String>();
		
		Table dbTable = this.getTableInfo(table.getTableName());
		List<String> sqlList = new ArrayList<String>();
		boolean isUpdatePrimary = false;
		Set<String> dbPrimaryKey    = new HashSet<String>();
		Set<String> modelPrimaryKey = new HashSet<String>();
		
 		// 正向对比
		for (String columnName : table.getColumnToColumnMap().keySet()) {
			Column column = table.getColumnToColumnMap().get(columnName);
			if (dbTable.getColumnToColumnMap().containsKey(columnName) && dbTable.getColumnToColumnMap().get(columnName) != null) {
				//String dbColumnName = StringUtils.firstCharLowercase(fieldName);
				//String dbColumnName = table.getColumnName(fieldName);
				Column dbColumn = dbTable.getColumnToColumnMap().get(columnName);
				
				String sql = getAlterColumnCommands(table.getTableName(), dbColumn, column,commonds);
				if(StringUtils.isNotEmpty(sql)) {
					sqlList.add(sql);
				}
				
				
				if(dbColumn.isPrimary()) {
					dbPrimaryKey.add(dbColumn.getName());
				}
				if(column.isPrimary()) {
					modelPrimaryKey.add(column.getName());
				}
			} else {
				// 添加此字段
				sqlList.add(getAddColumnCommands(table.getTableName(), column,commonds));
				if(!isUpdatePrimary&&column.isPrimary()) {
					isUpdatePrimary = true;
				}
			}
		}
		// 反向比较删除字段
		for (String columnName : dbTable.getColumnToColumnMap().keySet()) {
			if (!table.getColumnToColumnMap().containsKey(columnName)) {
				sqlList.add(getDelColumnCommands(table.getTableName(),columnName));
			}
		}
		// 主键修改
		if(!isEquallyPrimary(dbPrimaryKey,modelPrimaryKey)) {
			if(dbPrimaryKey.size()>0) {
				sqlList.add("DROP PRIMARY KEY");
			}
			if(modelPrimaryKey!=null&&modelPrimaryKey.size()>0) {
				StringBuffer p=new StringBuffer();
				p.append("ADD PRIMARY KEY (");
				int i=0;
				for(String n:modelPrimaryKey) {
					if(i==0) {
						p.append("`"+n+"`");
					}else {
						p.append(",`"+n+"`");
					}
					i++;
				}
				p.append(") USING BTREE");
				sqlList.add(p.toString());
			}
		}
		
		if(sqlList!=null&&!sqlList.isEmpty()) {
			StringBuffer sb= new StringBuffer();
			sb.append(" ALTER TABLE `"+table.getTableName()+"` ");
			int indexEnd = (sqlList.size()-1);
			for(int i=0;i<sqlList.size();i++) {
				if(i==indexEnd) {
					sb.append(" "+sqlList.get(i)+";");
				}else {
					sb.append(" "+sqlList.get(i)+",");
				}
			}
			
			commonds.add(0, sb.toString());
		}
		return commonds;
	}

	private boolean isEquallyPrimary(Set<String> dbPrimaryKey, Set<String> modelPrimaryKey) {
		if(dbPrimaryKey.size()!=modelPrimaryKey.size()) {
			return false;
		}
		for(String p:dbPrimaryKey) {
			if(!modelPrimaryKey.contains(p)) {
				return false;
			}
		}
		for(String p:modelPrimaryKey) {
			if(!dbPrimaryKey.contains(p)) {
				return false;
			}
		}
		return true;
	}

	@Override
	public String getColumnSql(Column column) {
		String dbtype = column.getType().getMysqlDBType();
		StringBuffer sb = new StringBuffer();
		sb.append(" `" + column.getName() + "` ");
		sb.append(" " + dbtype);
		if (column.getLength() == 0 && column.getPrecision() > 0) {
			sb.append("(10," + column.getPrecision() + ") ");
		}
		if (column.getLength() > 0 && column.getPrecision() == 0) {
			sb.append("(" + column.getLength() + ") ");
		}
		if (column.getLength() > 0 && column.getPrecision() > 0) {
			sb.append("(" + column.getLength() + "," + column.getPrecision() + ") ");
		}
		sb.append(column.isNull() == false ? " not null" : " null ");
		sb.append(column.getRemark() == null ? "" : " COMMENT '" + column.getRemark() + "'");
		return sb.toString();
	}

	
	private boolean isChangeDefaultValue(String dbcolumndefaultvalue,String columndefaultvalue) {
		if(dbcolumndefaultvalue!=null&&columndefaultvalue==null) {
			return true;
		}
		if(dbcolumndefaultvalue==null&&columndefaultvalue!=null) {
			return true;
		}
		if(dbcolumndefaultvalue!=null&&columndefaultvalue!=null) {
			return !dbcolumndefaultvalue.equals(columndefaultvalue);
		}
		return false;
	}
	
	@Override
	public String getAlterColumnCommands(String tableName, Column dbColumn, Column column,List<String> commands) {
		StringBuffer sb = new StringBuffer();
		
		// 比较默认值
		String dbcolumndefaultvalue = dbColumn.getDefaultValue() == null ? "" : dbColumn.getDefaultValue();
		String columndefaultvalue = column.getDefaultValue() == null ? "" : column.getDefaultValue();
		if (isChangeDefaultValue(dbcolumndefaultvalue,columndefaultvalue)) {
			if (!StringUtils.isEmpty(dbcolumndefaultvalue)) {
				commands.add("alter table " + tableName + " alter column `" + column.getName() + "` drop default;");
			}
			if (!StringUtils.isEmpty(columndefaultvalue)) {
				commands.add("alter table " + tableName + " alter column `" + column.getName() + "` set default '"+ columndefaultvalue + "';");
			}
		}
		
		// 比较名称是否一样
		if (!dbColumn.getName().equals(column.getName())) {
			//commands.add("ALTER TABLE " + tableName + " RENAME COLUMN `" + dbColumn.getName() + "` TO `" + column.getName()+"`; ");
			sb.append(" CHANGE COLUMN `"+dbColumn.getName()+"` "+this.getColumnSql(column));
		}else {
			boolean isModify = false;
			// 比较类型
			if (dbColumn.getType().getCode() != column.getType().getCode()) {
				log.info("--------------------"+tableName+"比较类型不一致{},{}--------------------",dbColumn.getType(),column.getType());
				sb.append("MODIFY COLUMN "+  this.getColumnSql(column));
				isModify = true;
			}
			//比较长度
			if(!isModify&&dbColumn.getLength()!=column.getLength()) {
				if(column.getType()!= ColumnType.TIMESTAMP&&column.getType()!=ColumnType.TINYINT) {
					log.info("--------------------"+tableName+"比较长度不一致{},{},{},{}--------------------",dbColumn.getType(),column.getType(),dbColumn.getLength(),column.getLength());
					sb.append("MODIFY COLUMN "+  this.getColumnSql(column));
					isModify = true;
				}
			}
			
			if(!isModify&&dbColumn.isNull()!=column.isNull()) {
				log.info("--------------------"+tableName+"比较nullable不一致{},{},{},{}--------------------",dbColumn.isNull(),column.isNull(),dbColumn.getPrecision(),column.getPrecision());
				sb.append("MODIFY COLUMN "+  this.getColumnSql(column));
				isModify = true;
			}
			
			//比较精度
			if(!isModify&&dbColumn.getPrecision()!=column.getPrecision()) {
				log.info("--------------------"+tableName+"比较精度不一致{},{},{},{}--------------------",dbColumn.getType(),column.getType(),dbColumn.getPrecision(),column.getPrecision());
				sb.append("MODIFY COLUMN "+  this.getColumnSql(column));
				isModify = true;
			}
			// 比较备注
			if (!isModify&&!dbColumn.getRemark().equals(column.getRemark())) {
				log.info("--------------------"+tableName+"比较备注不一致{},{},{},{}--------------------",dbColumn.getType(),column.getType(),dbColumn.getRemark(),column.getRemark());
				sb.append("MODIFY COLUMN "+  this.getColumnSql(column));
			}
			
	
		}
		return sb.toString();
	}

	@Override
	public String getAddColumnCommands(String tableName, Column column,List<String> commands) {
		String columndefaultvalue = column.getDefaultValue() == null ? "" : column.getDefaultValue();
		if (!StringUtils.isEmpty(columndefaultvalue)) {
			commands.add("alter table " + tableName + " alter column `" + column.getName() + "` set default '"+ columndefaultvalue + "';");
		}
		
		return "ADD COLUMN "+this.getColumnSql(column) ;
	}

}
